<?php
namespace yphp;

final class Redis extends Instance
{
    // 数据库连接列表
    private static $links = [];

    // 从数据库数组
    private $slave = [];

    // 构造函数
    function construct()
    {
        $slave = Config::nosql('redis.slave');
        empty($slave) || $slave = [Config::nosql('redis.master')];
        foreach ($slave as $k => $v) {
            is_int($k) ? $this->slave[$v] = 1 : $this->slave[$k] = $v;
        }
        return self::single();
    }

    // 获取数据库连接：主、从
    function masterLink()
    {
        return self::connect(Config::nosql('redis.master'));
    }

    function slaveLink()
    {
        return self::connect(Random::instance($this->slave)->getNode());
    }

    // 获取数据库连接
    protected static function connect($node)
    {
        if (key_exists($node, self::$links)) {
            $link = self::$links[$node];
        } else {
            $link = new \Redis();
            call_user_func_array([$link, 'connect'], explode(':', $node));
            $auth = Config::nosql('redis.auth');
            key_exists($node, $auth) && call_user_func([$link, 'auth'], $auth[$node]);
            self::$links[$node] = $link;
        }
        return $link;
    }

    // 常规操作
    static function __callStatic($name, $args)
    {
        $alias = substr($name, 0, 1) === '_';
        $name = $alias ? substr($name, 1) : $name;
        if (in_array(strtoupper($name), ['FLUSHDB','SLAVEOF','SAVE','BGSAVE','MOVE','LINSERT','RENAME','EXPIRE','SETBIT','APPEND','SETRANGE','SUBSTR','INCR','INCRBY','SETEX','SETNX','SET','ZADD','HSET','LPUSH','ZREM','ZSCORE','RPUSH','RPOP','LPOP','LSET','LTRIM','LREM','HDEL','SADD','SREM','SPOP','SINTERSTORE','SDIFF','SDIFFSTORE'])) {
            $node = 'masterLink';
        } elseif (in_array(strtoupper($name), ['LASTSAVE','INFO','LLEN','LINDEX','TTL','DBSIZE','RANDOMKEY','GETBIT','STRLEN','EXISTS','DEL','TYPE','GET','ZRANGE','ZCARD','ZRANGE','ZCOUNT','HGET','LRANGE','LSIZE','HKEYS','HVALS','HGETALL','SMEMBERS','SISMEMBER','SACRD','SINTER','SMOVE'])) {
            $node = 'slaveLink';
        } else return;
        $key = $alias ? array_shift($args) : $args[0];
        $redis = self::instance()->{$node}($key);
        return call_user_func_array([$redis, $name], $args);
    }

    // 关闭指定连接
    static function close($node)
    {
        key_exists($node, self::$links) && self::$links[$node]->close();
    }

    // 关闭所有连接
    static function closeAll()
    {
        foreach (self::links as $link) {
            $link->close();
        }
    }

}